package com.feige.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.feige.entity.SecurityUser;
import com.feige.entity.User;
import com.feige.result.AjaxResult;
import com.feige.utils.jwt.JwtUtils;
import com.feige.utils.redis.RedisUtils;
import com.feige.utils.http.ResponseUtil;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

/**
 * 登录过滤器，继承UsernamePasswordAuthenticationFilter，对用户名密码进行登录校验
 */
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private RedisUtils redisUtils;

    private AuthenticationManager authenticationManager;

    public TokenLoginFilter(AuthenticationManager authenticationManager, RedisUtils redisUtils) {
        this.authenticationManager = authenticationManager;
        this.redisUtils = redisUtils;
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/login","POST"));
    }

    /**
     * 尝试认证
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword(),new ArrayList<>()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 认证成功
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        SecurityUser user = (SecurityUser)authResult.getPrincipal();
        String token = JwtUtils.getJwtToken(user.getCurrentUser().getUsername());
        user.setUuid(token);
        user.setLoginTime(System.currentTimeMillis());
        user.setExpireTime(System.currentTimeMillis() + 1800);
        redisUtils.set(user.getCurrentUser().getUsername(), user,1800);
        AjaxResult success = AjaxResult.success();
        success.put("token",token);
        ResponseUtil.out(response, success);
    }

    /**
     * 认证不成功
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        AjaxResult ajaxResult = new AjaxResult();
        ajaxResult.put("code","500");
        ajaxResult.put("msg","认证不成功");
        ResponseUtil.out(response,ajaxResult);
    }
}
